import { exec, execSync } from "child_process";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
import path from "path";
import iconv from "iconv-lite";
import * as vscode from "vscode";
import { createHash } from "crypto";
import { mirServer } from "./extension";

export function cache(name: string, value?: any) {
  const context = mirServer?.context;
  if (!context) {
    return;
  }
  const key = `mirServer.${name}`;
  if (value !== undefined) {
    return context.workspaceState.update(key, value);
  }
  return context.workspaceState.get(key);
}
export function strPatternToRegExp(pattern: string): RegExp | undefined {
  const match = pattern.match(/^\/(.+)\/([gimsuy]*)$/);
  if (match) {
    return new RegExp(match[1], match[2] || undefined);
  }

  if (pattern.includes("*")) {
    const replacedStr = pattern.replace(/(\*)|(\.)/g, (match, star, dot) => {
      if (star) {
        return ".*";
      }
      if (dot) {
        return "\\.";
      }
      return match;
    });
    return new RegExp(replacedStr, "i");
  }
}

export function findPortsByProcessIdAsync(processId: number): Promise<number[]> {
  return new Promise((resolve, reject) => {
    if (!Number.isInteger(processId) || processId < 0) {
      return resolve([]);
    }
    const command = `chcp 65001 > nul && netstat -ano | findstr "${processId}"`;
    exec(`${command} 2> nul`, (error, output) => {
      if (error) {
        return reject(error);
      }
      // 匹配 IP:Port 格式中的端口号部分
      const portMatches = output.match(/(?<=\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:)\d+/g);
      const list = portMatches?.filter((v) => v !== "0").map((v) => parseInt(v, 10)) ?? [];
      resolve(list);
    });
  });
}
export function findPortsByProcessId(processId: number): number[] {
  if (!Number.isInteger(processId) || processId < 0) {
    return [];
  }

  let command: string;
  if (process.platform === "win32") {
    // Windows 平台使用 chcp 切换编码并执行 netstat 命令
    command = `chcp 65001 > nul && netstat -ano | findstr "${processId}"`;
  } else {
    // 非 Windows 平台暂不支持，可根据实际需求扩展
    return [];
  }

  try {
    const output = execSync(`${command} 2> nul`, { encoding: "utf8" });

    // 匹配 IP:Port 格式中的端口号部分
    const portMatches = output.match(/(?<=\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:)\d+/g);

    return portMatches?.filter((v) => v !== "0").map((v) => parseInt(v, 10)) ?? [];
  } catch (error) {
    // console.error('执行命令失败:', error.message);
    return [];
  }
}

type ProcessInfo = {
  ProcessId: number;
  ExecutablePath: string;
  Name: string;
};

function parseWmicProcessOutput(output: string) {
  const lines = output
    .split("\r\n")
    .map((line) => line.trim())
    .filter((line) => line.length > 0);
  if (lines.length < 2) {
    return [];
  }

  const headers = lines[0].split(",").map((h) => h.trim());
  const nameIndex = headers.indexOf("Name");
  const executablePathIndex = headers.indexOf("ExecutablePath");
  const processIdIndex = headers.indexOf("ProcessId");

  // 确保关键字段存在
  if (nameIndex === -1 || executablePathIndex === -1 || processIdIndex === -1) {
    return [];
  }
  return lines.slice(1).reduce<{ ProcessId: number; ExecutablePath: string; Name: string }[]>((acc, line) => {
    const values = line.split(",").map((v) => v.trim());
    const name = values[nameIndex];
    const executablePath = values[executablePathIndex];
    const processId = values[processIdIndex];

    if (!executablePath || !processId) {
      return acc;
    }
    acc.push({
      Name: name,
      ProcessId: parseInt(processId),
      ExecutablePath: executablePath,
    });
    return acc;
  }, []);
}

export function findProcessesByFilenameAsync(filename: string): Promise<ProcessInfo[]> {
  return new Promise((resolve, reject) => {
    // 对 filename 进行转义，防止命令注入
    const safeFilename = path.basename(filename).replace(/"/g, '\\"');
    const command = `chcp 65001 > nul && wmic process where name="${safeFilename}" get processid,executablepath,name /format:csv`;
    exec(`${command} 2> nul`, (err, output) => {
      if (err) {
        return reject(err);
      }
      const list = parseWmicProcessOutput(output).filter((line) => line.ExecutablePath === filename);
      return resolve(list);
    });
  });
}

export function findProcessesByFilename(filename: string) {
  // 对 filename 进行转义，防止命令注入
  const safeFilename = path.basename(filename).replace(/"/g, '\\"');
  const command = `chcp 65001 > nul && wmic process where name="${safeFilename}" get processid,executablepath,name /format:csv`;

  const buf = execSync(`${command} 2> nul`);
  const output = iconv.decode(buf, "gb2312");
  return parseWmicProcessOutput(output).filter((line) => line.ExecutablePath === filename);
}

export const sleep = (ms: number) => {
  return new Promise((resolve) => setTimeout(resolve, ms));
};

export function getWorkspaceSettingsFilename(workspace: vscode.WorkspaceFolder) {
  const folder = vscode.workspace.getWorkspaceFolder(workspace?.uri);
  if (!folder) {
    return false;
  }
  const vscodeFolderPath = path.join(folder.uri.fsPath, ".vscode");
  if (!existsSync(vscodeFolderPath)) {
    mkdirSync(vscodeFolderPath, { recursive: true });
  }

  const settingsFilePath = path.join(vscodeFolderPath, "settings.json");
  if (!existsSync(settingsFilePath)) {
    const defaultSettings = {};
    writeFileSync(settingsFilePath, JSON.stringify(defaultSettings, null, 2), {
      encoding: "utf8",
    });
  }
  return settingsFilePath;
}
/**
 * 打开指定工作区的settings.json文件（自动创建）
 * @param workspace
 * @returns
 */
export function openSettingsFile(workspace: vscode.WorkspaceFolder) {
  const settingsFilePath = getWorkspaceSettingsFilename(workspace);
  if (settingsFilePath) {
    // 打开 settings.json 文件进行编辑（可选）
    const fileUri = vscode.Uri.file(settingsFilePath);
    vscode.commands.executeCommand("vscode.open", fileUri);
  }
}

export async function readSettings(workspace: vscode.WorkspaceFolder) {
  const settingsFilePath = getWorkspaceSettingsFilename(workspace);
  if (!settingsFilePath) {
    return;
  }
  let settings: Record<string, any> = {};
  try {
    const str = readFileSync(settingsFilePath, "utf8");
    settings = JSON.parse(str);
  } catch (error) {}
  return settings;
}

export async function writeSettings(workspace: vscode.WorkspaceFolder, settings: Record<string, any>) {
  const settingsFilePath = getWorkspaceSettingsFilename(workspace);
  if (!settingsFilePath) {
    return false;
  }
  writeFileSync(settingsFilePath, JSON.stringify(settings, null, 2), {
    encoding: "utf8",
  });
  return true;
}

/**
 *
 * @param uri 根据Uri获取工作区目录，为空时，获取当前激活的编辑器工作区目录
 * @returns
 */
export function getWorkspaceFolder(uri?: vscode.Uri) {
  if (uri) {
    return vscode.workspace.getWorkspaceFolder(uri);
  }
  return getActiveWorkspaceFolder();
}
export function getActiveWorkspaceFolder() {
  const activate = vscode.window.activeTextEditor;
  if (!activate) {
    return;
  }
  return vscode.workspace.getWorkspaceFolder(activate.document.uri);
}

export function makeHash(str: string) {
  return createHash("md5").update(str).digest("hex");
}
